/* Copyright 2009 Requirements Management System 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mags.common.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.validator.GenericValidator;
import org.hibernate.SessionFactory;
import org.mags.dao.hibernate.DAO;
import org.mags.dao.provider.AbstractProviderFactory;
import org.mags.remas.model.commons.AuditInterceptor;
import org.mags.remas.model.commons.DataSourceInformation;
import org.mags.remas.model.entity.provider.EntityProviderFactory;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;

/**
 * 
 * @author Mario Gaitan
 *
 */
public class DataContextBase extends org.mags.dao.provider.DataAccess {
	private String password;
	private BasicDataSource dataSource;
	private Map<String, String> properties=null;
	
	public void setDataSourceInformation(DataSourceInformation dataSourceInformation) {
		resetAttributes();
		dataSource = new BasicDataSource();
		dataSource.setDriverClassName(dataSourceInformation.getDriverName());
		dataSource.setUrl(dataSourceInformation.getUrl());
		dataSource.setUsername(dataSourceInformation.getUsername());
		dataSource.setPassword(dataSourceInformation.getPassword());
		dataSource.setDefaultCatalog(dataSourceInformation.getDefaultCatalog());
		properties = dataSourceInformation.getProperties();
		loadDAO();
	}
	private void resetAttributes() {
		properties=new HashMap<String, String>();
		if(dataSource!=null) {
			try {
				dataSource.close();
			} catch (Exception e) {
				/*IGNORE EXCEPTION*/
			}
		}
		dataSource = null;
	}
	public Map<String, String> getProperties() {
		return properties;
	}
	public String getProperty(String key) {
		return properties.get(key);
	}
	public void addProperty(String key, String value) {
		properties.put(key, value);
	}
	public BasicDataSource getDataSource() {
		return dataSource;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public DataContextBase(){		
		resetAttributes();
	}
	private void loadDAO() {
		DAO dao = new DAO();
		SessionFactory sessionFactory = makeSessionFactory();	
		HibernateTransactionManager transactionManager = new HibernateTransactionManager();
		dao.setSessionFactory(sessionFactory);
		transactionManager.setSessionFactory(sessionFactory);
		List<AbstractProviderFactory> providerFactories = new ArrayList<AbstractProviderFactory>();
		providerFactories.add(new EntityProviderFactory());
		setDao(dao);
		setTransactionManager(transactionManager);
		setProviderFactories(providerFactories);
	}
	private SessionFactory makeSessionFactory() {
		Properties hibernateProperties = new Properties();
		for(String key: properties.keySet()) 
			if(key.startsWith("hibernate")) 
				hibernateProperties.setProperty(key, getProperty(key));
		hibernateProperties.setProperty("hibernate.show_sql", "true");
		hibernateProperties.setProperty("hibernate.cache.enabled", "false");
		hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false");
		hibernateProperties.setProperty("hibernate.cache.use_query_cache", "false");
		hibernateProperties.setProperty("hibernate.connection.aggressive_release", "false");
		hibernateProperties.setProperty("hibernate.cache.provider_class", "false");
		hibernateProperties.setProperty("hibernate.cache.use_minimal_puts", "false");
		hibernateProperties.setProperty("hibernate.current_session_context_class", "thread");
		
		hibernateProperties.setProperty("hibernate.connection.url", dataSource.getUrl());
		if(!GenericValidator.isBlankOrNull(dataSource.getUsername()))
			hibernateProperties.setProperty("hibernate.connection.username", dataSource.getUsername());
		if(!GenericValidator.isBlankOrNull(dataSource.getPassword()))
			hibernateProperties.setProperty("hibernate.connection.password", dataSource.getPassword());
		hibernateProperties.setProperty("hibernate.connection.driver_class", dataSource.getDriverClassName());
		if(!GenericValidator.isBlankOrNull(dataSource.getDefaultCatalog()))
			hibernateProperties.setProperty("hibernate.connection.default_catalog", dataSource.getDefaultCatalog());
		AuditInterceptor.getInstance().setUserName(dataSource.getUsername());
		
		String hbmPackage = getProperty("hbm_package");
		String[] resources = new String[]{
			hbmPackage+"Entity.hbm.xml"
			,hbmPackage+"EntityRelationship.hbm.xml"
			,hbmPackage+"EntityStructure.hbm.xml"
			,hbmPackage+"EntityType.hbm.xml"
			,hbmPackage+"EntityCategory.hbm.xml"
			,hbmPackage+"EntityStatus.hbm.xml"
			,hbmPackage+"ViewType.hbm.xml"
			,hbmPackage+"LinkStructure.hbm.xml"
			,hbmPackage+"EntityFile.hbm.xml"
			,hbmPackage+"KeyType.hbm.xml"
			,hbmPackage+"EnumName.hbm.xml"
			,hbmPackage+"EnumValue.hbm.xml"
			,hbmPackage+"KeyDefinition.hbm.xml"
			,hbmPackage+"KeyValue.hbm.xml"
			,hbmPackage+"ListName.hbm.xml"
			,hbmPackage+"ListValue.hbm.xml"
			,hbmPackage+"EntityComment.hbm.xml"
			,hbmPackage+"CommentType.hbm.xml"
			,hbmPackage+"EntityReference.hbm.xml"
			,hbmPackage+"ReferenceStatus.hbm.xml"
			,hbmPackage+"SystemProperty.hbm.xml"
			,hbmPackage+"SystemListValue.hbm.xml"
		};		
		LocalSessionFactoryBean beanSessionFactory = new LocalSessionFactoryBean();			
		beanSessionFactory.setHibernateProperties(hibernateProperties);
		beanSessionFactory.setDataSource(dataSource);
		beanSessionFactory.setEntityInterceptor(AuditInterceptor.getInstance());
		beanSessionFactory.setMappingResources(resources);
		try {
			beanSessionFactory.afterPropertiesSet();
		} catch (Exception e) {
			if(e instanceof RuntimeException)
				throw (RuntimeException)e;
			else
				throw new RuntimeException(e);
		}			
		return (SessionFactory)beanSessionFactory.getObject();
	}
}
